#ifndef RTPS_SEDPAGENT_T
#define RTPS_SEDPAGENT_T

// #include "rtps/entities/Participant.h"
#include "rtps/discovery/BuiltInEndpoints.h"
#include "rtps/storages/MemoryPool.h"
#include "rtps/discovery/TopicData.h"
#include "rtps/common/types.h"
#include <pthread.h>
#include <stddef.h>
#include <stdint-gcc.h>

// typedef struct sys_mutex* sys_mutex_t;

// struct sys_mutex {
//   pthread_mutex_t mutex;
// };

struct rtps_Participant;
struct rtps_ReaderCacheChange;
struct rtps_Writer;
struct rtps_Reader;

struct rtps_SEDPAgent {
	int type;
	struct rtps_Participant *m_part;
	sys_mutex_t m_mutex;
	uint8_t m_buffer[600]; // TODO check size, currently changed from 300 to 600
                         // (FastDDS gives too many options)
	struct rtps_BuiltInEndpoints m_endpoints;
	/**
	 * If we add readers later on, remote participants will not send matching
	 * writer proxies again (and vice versa). This is done only once during
	 * discovery. Therefore, we need to keep track of remote endpoints. Topic and
	 * type are represented as hash values to save memory.
	**/
	struct rtps_MemoryPool *m_unmatchedRemoteWriters;
	size_t m_numUnmatchedRemoteWriters;
	struct rtps_MemoryPool *m_unmatchedRemoteReaders;
	size_t m_numMatchedRemoteReaders;

	void (*mfp_onNewPublisherCallback)(void *arg);
	void *m_onNewPublisherArgs;
	void (*mfp_onNewSubscriberCallback)(void *arg);
	void *m_onNewSubscriberArgs;
};

/* private */
void rtps_SEDPAgent_tryMatchUnmatchedEndpoints(struct rtps_SEDPAgent *this);
void rtps_SEDPAgent_addUnmatchedRemoteWriter(struct rtps_SEDPAgent *this, const struct rtps_TopicData *writerData);
void rtps_SEDPAgent_addUnmatchedRemoteReader(struct rtps_SEDPAgent *this, const struct rtps_TopicData *readerData);

void rtps_SEDPAgent_receiveCallbackPublisher(void *callee, const struct rtps_ReaderCacheChange *cacheChange);
void rtps_SEDPAgent_receiveCallbackSubscriber(void *callee, const struct rtps_ReaderCacheChange *cacheChange);
void rtps_SEDPAgent_onNewPublisher_ReaderCacheChange(struct rtps_SEDPAgent *this, const struct rtps_ReaderCacheChange *change);
void rtps_SEDPAgent_onNewSubscriber_ReaderCacheChange(struct rtps_SEDPAgent *this, const struct rtps_ReaderCacheChange *change);

/* public */
void rtps_SEDPAgent_init(struct rtps_SEDPAgent *this, struct rtps_Participant *part, const struct rtps_BuiltInEndpoints *endpoints);
void rtps_SEDPAgent_deinit(struct rtps_SEDPAgent *this);
void rtps_SEDPAgent_addWriter(struct rtps_SEDPAgent *this, struct rtps_Writer *writer);
void rtps_SEDPAgent_addReader(struct rtps_SEDPAgent *this, struct rtps_Reader *reader);
void rtps_SEDPAgent_registerOnNewPublisherMatchedCallback(struct rtps_SEDPAgent *this, void (*callback)(void *arg), void *args);
void rtps_SEDPAgent_registerOnNewSubscriberMatchedCallback(struct rtps_SEDPAgent *this, void (*callback)(void *arg), void *args);

/* protected - For testing purposes */
void rtps_SEDPAgent_onNewPublisher_TopicData(struct rtps_SEDPAgent *this, const struct rtps_TopicData *writerData);
void rtps_SEDPAgent_onNewSubscriber_TopicData(struct rtps_SEDPAgent *this, const struct rtps_TopicData *writerData);

#endif /* RTPS_SEDPAGENT */
